package com.getan.boot.web.web;

import com.getan.boot.common.encrypt.JasyptService;
import com.getan.boot.common.spring.SpringContextHolder;
import com.getan.boot.common.utils.DateHelper;
import com.getan.boot.web.web.exception.ApplicationExceptionHandler;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
import org.springframework.lang.NonNull;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Servlet Web自动配置类
 *
 * @author Bruce.Gong
 * @since 1.0.0-SNAPSHOT
 */
@ConditionalOnWebApplication
public class GetanWebAutoConfiguration implements WebMvcConfigurer {

    /**
     * 跨域访问，参数文档：<https://www.ruanyifeng.com/blog/2016/04/cors.html>
     * <p>
     * mapping：允许跨域访问的路径
     * origins：对应 Access-Control-Allow-Origin 请求头，只接受指定域名的跨域访问，* 表示接受任意域名的请求
     * methods：对应 access-control-allow-methods 请求头，只接受指定请求方式的跨域访问，* 表示接受任意请求方式的请求
     * exposedHeaders：对应 access-control-expose-headers 请求头，
     * CORS请求时，XMLHttpRequest 对象的 getResponseHeader()方法只能拿到 6 个基本字段：Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma，
     * 如果想拿到其他请求头，就必须在 Access-Control-Expose-Headers 里面指定
     * headers：对应 access-control-allow-headers 请求头，请求方会额外发送的请求头
     * credentials：对应 access-control-allow-credentials 请求头，CORS请求默认不发送 Cookie 和 HTTP 认证信息，true 表示可以发送，需要与客户端保持一致
     * maxAge：对应 access-control-max-age 请求头
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowedMethods("GET", "POST", "OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(false)
                .exposedHeaders("*")
                .maxAge(3600);
    }

    /**
     * 注册 Spring 容器
     *
     * @return SpringContextHolder
     */
    @Bean
    public SpringContextHolder springContextHolder() {
        return new SpringContextHolder();
    }

    /**
     * 全局异常处理
     *
     * @return ServletExceptionHandler
     */
    @Bean
    @ConditionalOnMissingBean
    public ApplicationExceptionHandler applicationExceptionHandler() {
        return new ApplicationExceptionHandler();
    }

    /**
     * 配置 GET 请求参数中时间类型转换
     *
     * @param registry FormatterRegistry
     */
    @Override
    public void addFormatters(@NonNull FormatterRegistry registry) {
        DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
        registrar.setTimeFormatter(DateHelper.TIME_FORMATTER);
        registrar.setDateFormatter(DateHelper.DATE_FORMATTER);
        registrar.setDateTimeFormatter(DateHelper.DATE_TIME_FORMATTER);
        registrar.registerFormatters(registry);
    }

    @Bean
    @ConditionalOnMissingBean
    public JasyptService jasyptService() {
        return new JasyptService();
    }

}
